
#include <string.h>
#include <stdio.h>
#include <stdarg.h>


#define tc_log(_fmt_, ...)          printf("[TC][%s:%d][%s] "_fmt_"\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)
#define tc_log_err(_fmt_, ...)      printf("[TC][ERR][%s:%d][%s] "_fmt_"\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)


static void hexdump(unsigned char *buf, int len, const char *str, ...)
{
	int i;

	va_list args;
 	va_start(args, str);
	vprintf(str, args);
	va_end(args);

	for (i = 0; i < len; ++i) {
		if (i % 16 == 0) {
			if (i >= 16)
				printf("\t\t%.*s", 16, buf + i - 16);

			printf("\n%p:", buf + i);
		}
		printf(" %02x", buf[i]);
	}
	printf("\033[%dC\t\t%.*s\n", (16 - (i & 0x7)) * 3, i & 0x7, buf + (i & ~0x7));
}

int lengthOfLongestSubstring_2(char * s)
{
	char *b, *p;
	int i, total_len, curr_len, max_len;

	if (s == NULL || strlen(s) == 0) {
		tc_log("s %p strlen(s) %d", s, strlen(s));
		return 0;
	}
		
	b = s;
	p = b + 1;

	total_len = strlen(s);
	curr_len = max_len = 1;

	if (total_len <= 1)
		return total_len;

	while (1) {

		tc_log("*s: %c *b: %c *p: %c total_len: %d curr_len: %d max_len: %d", *s, *b, *p, total_len, curr_len, max_len);

		for (i = 0; i < curr_len; ++i) {
			tc_log("*b: %c *p: %c *(b + %d): %c", *b, *p, i, *(b + i));
			if (*p == *(b + i))
				break;
		}

		tc_log("i: %d curr_len: %d", i, curr_len);
		if (i == curr_len) {
			curr_len++;
			p++;

			if (max_len < curr_len)
				max_len = curr_len;
		}
		else {
			b++;
			curr_len = 1;
			p = b + 1;
		}

		if (p >= s + total_len)
			break;	// over
	}

	return max_len;
}

int lengthOfLongestSubstring(char * s)
{
	char *b, *p;
	int i, total_len, curr_len, max_len;

	if (s == NULL || strlen(s) == 0) {
		tc_log("s %p strlen(s) %d", s, strlen(s));
		return 0;
	}
		
	b = s;
	p = b + 1;

	total_len = strlen(s);
	curr_len = max_len = 1;

	if (total_len <= 1)
		return total_len;

	while (1) {

		tc_log("*s: %c *b: %c *p: %c total_len: %d curr_len: %d max_len: %d", *s, *b, *p, total_len, curr_len, max_len);

		for (i = 0; i < curr_len; ++i) {
			tc_log("*b: %c *p: %c *(b + %d): %c", *b, *p, i, *(b + i));
			if (*p == *(b + i))
				break;
		}

		tc_log("i: %d curr_len: %d", i, curr_len);
		if (i == curr_len) {
			curr_len++;
			p++;

			if (max_len < curr_len)
				max_len = curr_len;
		}
		else {
			b++;
			curr_len = 1;
			p = b + 1;
		}

		if (p >= s + total_len)
			break;	// over
	}

	return max_len;
}

int main(int argc, char const *argv[])
{
	char input[64];

	tc_log("********************");
	tc_log("new start @ %s %s", __DATE__, __TIME__);
	tc_log("********************");

	tc_log("input:");
	fgets(input, sizeof(input), stdin);
	hexdump(input, strlen(input), "%s %s user input:", __DATE__, __TIME__);

	input[strlen(input) - 1] = 0x00;
	hexdump(input, strlen(input), "remove \\n input:");

	tc_log("ret %d", lengthOfLongestSubstring(input));

	tc_log("exit");
	return 0;
}

